package cn.da.shuai.cool.common.web.wrapper;

import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.*;

/**
 * 可重复读取的请求包装器
 */
@Slf4j
public class ReusableRequestWrapper extends HttpServletRequestWrapper {
    @Getter
    private final byte[] body;
    private BufferedReader reader;
    private ServletInputStream inputStream;

    public ReusableRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        // 读取请求体并保存
        body = request.getInputStream().readAllBytes();
    }

    @Override
    public BufferedReader getReader() throws IOException {
        if (inputStream != null) {
            throw new IllegalStateException("getInputStream() has already been called on this request.");
        }
        if (reader == null) {
            reader = new BufferedReader(new InputStreamReader(getInputStream()));
        }
        return reader;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (reader != null) {
            throw new IllegalStateException("getReader() has already been called on this request.");
        }
        if (inputStream == null) {
            inputStream = new ServletInputStream() {
                private final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);

                @Override
                public boolean isFinished() {
                    return byteArrayInputStream.available() == 0;
                }

                @Override
                public boolean isReady() {
                    return true;
                }

                @Override
                public void setReadListener(ReadListener readListener) {
                    throw new UnsupportedOperationException("ReadListener is not supported");
                }

                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }

                @Override
                public int read(byte[] b, int off, int len) throws IOException {
                    return byteArrayInputStream.read(b, off, len);
                }

                @Override
                public void close() throws IOException {
                    super.close();
                    byteArrayInputStream.close();
                }
            };
        }
        return inputStream;
    }

}